package com.yunxin.facerecognition.activity;

import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.ShutterCallback;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;

import com.common.manager.ThreadManager;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import id.zelory.compressor.Compressor;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;


public class CameraControler {

    private final static String TAG = "CameraControler";


    private SurfaceHolder holder;

    private SurfaceView mSurfaceView;

    private Camera camera;
    private Camera.Parameters parameters;


    private MyAutoFocusCallback myAutoFocusCallback;
    private MySurfaceHolderCallback mySurfaceHolderCallback;
    private MyCameraPictureCallback myCameraPictureCallback;

    private int mInterval = 3000;//ms

    public CameraControler(SurfaceView surfaceView) {
        Log.d(TAG, "CameraControler construted");

        myCameraPictureCallback = new MyCameraPictureCallback();
        myAutoFocusCallback = new MyAutoFocusCallback();
        mySurfaceHolderCallback = new MySurfaceHolderCallback();

        updateSurfaceView(surfaceView);
        initCamera();
    }

    public void updateSurfaceView(SurfaceView surfaceView) {
        mSurfaceView = surfaceView;

        if (mSurfaceView == null) {
            Log.e(TAG, "surfaceView==null");
        } else {
            Log.d(TAG, "surfaceView!=null");
        }
        holder = mSurfaceView.getHolder();
        holder.addCallback(mySurfaceHolderCallback);
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void setInterval(int interval) {
        mInterval = interval;
    }

    private void initCamera() {
        int frontCameraId = -1;
        int numberOfCameras = Camera.getNumberOfCameras();
        CameraInfo cameraInfo = new CameraInfo();
        for (int i = 0; i < numberOfCameras; i++) {
            Camera.getCameraInfo(i, cameraInfo);
            if (cameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT) {
                frontCameraId = i;
            }
        }
        Log.e(TAG, "frontCameraId = "+frontCameraId);
        if (frontCameraId == -1) {
            if (numberOfCameras > 0) {
                frontCameraId = 0;
            } else {
                Log.e(TAG, "no camera can open!");
                return;
            }
        }
        try {
            camera = Camera.open(frontCameraId);
        }catch (Exception e){
            Log.e(TAG, "1----------------- e:" + e);
            releaseCamera();
            return;
        }

        if (holder != null) {
            try {
                camera.cancelAutoFocus();
                camera.setPreviewDisplay(holder);
                parameters = camera.getParameters();
                camera.setParameters(parameters);
                camera.setDisplayOrientation(270);
                camera.startPreview();

            } catch (IOException e) {
                e.printStackTrace();
            }
        }

     /*   List<Camera.Size> previewSizes = camera.getParameters().getSupportedPreviewSizes();
        for (int i = 0; i < previewSizes.size(); i++) {
            Camera.Size psize = previewSizes.get(i);
            Log.i(TAG , "PreviewSize,width: " + psize.width + " height: " + psize.height);
        }*/
    }

    public void releaseCamera() {
        if (camera != null) {
            camera.stopPreview();
            camera.release();
            camera = null;

        }
    }

    public void startTakingPhotos() {
        Log.d(TAG, "startTakingPhotos()");
        mSurfaceView.setVisibility(View.VISIBLE);
        VerifySignInActivity.binding.floatLlDescribe.setVisibility(View.GONE);
        ThreadManager.getIO().execute(new Runnable() {
            @Override
            public void run() {
                if (camera != null) {
                    Log.d(TAG, "camera!=null");
                    try {
                        Thread.sleep(mInterval);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    camera.autoFocus(myAutoFocusCallback);
                } else {
                    Log.d(TAG, "camera==null");
                }
            }
        });

    }


    public void stopTakingPhotos() {
    }


    class MyCameraPictureCallback implements Camera.PictureCallback {
        /**
         * callback this method after picture taken
         */
        public void onPictureTaken(byte[] data, Camera camera) {
            Log.i(TAG, "onPictureTaken()");

            File file = new File(Environment.getExternalStorageDirectory()
                    + "/backgroundCamera");

            if (!file.exists()) {
                file.mkdirs();
            }

            try {
                Date date = new Date();
                SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
                String time = format.format(date);
                String path = Environment.getExternalStorageDirectory()
                        + "/backgroundCamera/" + time + ".jpg";
                FileUtils.writeByteArrayToFile(new File(path), data, false);
                releaseCamera();

                //    camera.startPreview();
                new Compressor(mSurfaceView.getContext())
                        .compressToFileAsFlowable(new File(path))
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Consumer<File>() {
                            @Override
                            public void accept(File file) {
                                Log.d("MyCameraPictureCallback", file.getAbsolutePath());
                                mSurfaceView.setVisibility(View.GONE);
                                VerifySignInActivity.uploadFileReq(file);
                            }
                        }, new Consumer<Throwable>() {
                            @Override
                            public void accept(Throwable throwable) {
                                throwable.printStackTrace();
                            }
                        });

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    class MyAutoFocusCallback implements AutoFocusCallback {

        @Override
        public void onAutoFocus(boolean success, Camera camera) {
            Log.d(TAG, "onAutoFocus()");
            if (success) {
                Log.d(TAG, "onAutofocus() success==true");
            } else {
                Log.e(TAG, "onAutofocus() success==false");
            }

            camera.takePicture(new ShutterCallback() {
                @Override
                public void onShutter() {
                }
            }, null, myCameraPictureCallback);
        }
    }

    class MySurfaceHolderCallback implements SurfaceHolder.Callback {
        public void surfaceCreated(final SurfaceHolder holder) {
            Log.d(TAG, "surfaceCreated()");
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width,
                                   int height) {
            Log.d(TAG, "surfaceChanged()");
     /*       parameters = camera.getParameters();
            camera.setParameters(parameters);
            camera.startPreview();*/
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            Log.d(TAG, "surfaceDestroyed()");
        }
    }


}
